package hit.reports;

import hit.core.HomeInventoryTracker;
import hit.core.Item;
import hit.core.ItemIndex;
import hit.core.Product;
import hit.core.ProductContainer;
import hit.core.ProductGroup;
import hit.core.ProductIndex;
import hit.core.StorageUnit;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

/**
 * Builds a report for the list of ExpiredItems
 *
 */
public class ExpiredItemsReport implements ReportDesigner, Visitor {

	static final Comparator<Item> comp = new Comparator<Item>()
	{
		public int compare(Item i1, Item i2)
		{
			int result = i1.GetProduct().GetDescription()
								.compareTo(i2.GetProduct().GetDescription());
			
			if (result == 0)
			{
				result = i1.GetEntry().compareTo(i2.GetEntry());
			}
			
			return result;
		}
	};
	
	List<ProductContainer> containerOrder;
	Map<ProductContainer, List<Item> > expiredItems;
	
	public ExpiredItemsReport(){
		containerOrder = new ArrayList<ProductContainer>();
		expiredItems = new HashMap<ProductContainer, List<Item>>();
	}

	@Override
	public void VisitStorageUnit(StorageUnit unit) {
		containerOrder.add(unit);
	}

	@Override
	public void VisitProductGroup(ProductGroup group) {
		containerOrder.add(group);
	}
	
	@Override
	public void VisitItem(Item item) {
		Date expiration = item.GetExpiration();
		if (expiration != null && expiration.before(new Date())){
			if (expiredItems.containsKey(item.GetContainer())){
				expiredItems.get(item.GetContainer()).add(item);
			}
			else{
				List<Item> newList = new ArrayList<Item>();
				newList.add(item);
				expiredItems.put(item.GetContainer(), newList);
			}
		}
	}

	@Override
	public void BuildReport(ReportBuilder builder) {
		//Description, Storage Unit, Product Group, Entry Date, Expiration Date, Item Barcode
		
		builder.Clear();
		builder.setTitle("Expired Items");
		
		BuilderTable table = new BuilderTable();
		builder.AddObject(table);
		
		TableColumn descriptionCol = new TableColumn("Description");
		table.AddColumn(descriptionCol);
		
		TableColumn suCol = new TableColumn("Storage Unit");
		table.AddColumn(suCol);
		
		TableColumn pgCol = new TableColumn("Product Group");
		table.AddColumn(pgCol);
		
		TableColumn entryCol = new TableColumn("Entry Date");
		table.AddColumn(entryCol);
		
		TableColumn expireCol = new TableColumn("Expiration Date");
		table.AddColumn(expireCol);
		
		TableColumn barcodeCol = new TableColumn("Item Barcode");
		table.AddColumn(barcodeCol);
		
		Iterator<ProductContainer> pcIter = containerOrder.iterator();
		
		while (pcIter.hasNext())
		{
			List<Item> items = expiredItems.get(pcIter.next());
			if (items == null)
				continue;
			
			Collections.sort(items, comp);
			
			Iterator<Item> iIter = items.iterator();
			
			while (iIter.hasNext())
			{
				Item item = iIter.next();
				
				TableRow newRow = new TableRow();
				newRow.AddItem(descriptionCol, item.GetProduct().GetDescription());
				
				StorageUnit root = item.GetRootStorageUnit();
				ProductContainer container = item.GetContainer();
				newRow.AddItem(suCol, root.GetName());
				newRow.AddItem(pgCol, (root == container ? "" : container.GetName()));
				
				DateFormat formatter = new SimpleDateFormat(ReportBuilder.DATE_FORMAT);
				newRow.AddItem(entryCol, formatter.format(item.GetEntry()));
				newRow.AddItem(expireCol, formatter.format(item.GetExpiration()));
				newRow.AddItem(barcodeCol, item.GetBarcode().GetValue());
				
				table.AddRow(newRow);
			}
		}
	}
	
	@Override
	public void VisitHITCore(HomeInventoryTracker core) {/*do nothing*/}
	
	@Override
	public void VisitItemIndex(ItemIndex index) {/*do nothing*/}
	
	@Override
	public void VisitProduct(Product product) {
		throw new UnsupportedOperationException("Not applicable.");
	}
	
	@Override
	public void VisitProductIndex(ProductIndex index) {
		throw new UnsupportedOperationException("Not applicable.");
	}
	
	@Override
	public void VisitProductGroupPost(ProductGroup pg) {
		throw new UnsupportedOperationException("Not applicable.");
	}
}
